import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)

/**
 * The Main Protagonist of the game - Castlevania's Simon Belmont
 */
public class Simon  extends Actor implements Runnable
{
    private int speed;
    private int vSpeed;
    private int acceleration;
    private int jumpStrength;
    private retroWorld theWorld;
    private int halfImg;
    private int simonHalfWidth; //Coordinates of Simon's front or back
    
    private boolean isFacingRight;
    private boolean isJumping;
    private boolean isWhipping;
    private boolean isOnStairs;
    private boolean wasOnStairs;
    private boolean alive;
    private boolean pissedOff;
    private int stairDirection;
    
    public GreenfootImage[] whipRight;
    public GreenfootImage[] whipLeft;
    private GreenfootImage[] walkRight;
    private GreenfootImage[] walkLeft;
    
    Thread t;
    
    static int walkRightCounter = 0;
    static int walkLeftCounter = 0;
    
    Health health;
    WavPlayer soundBite;
    
    /** Constructor, initialize all of Simon's variables
     * 
     */
    public Simon()
    {
    speed = 7; //Movement speed      
    vSpeed = 0; //Current falling speed
    acceleration = 1; //Falling speed
    jumpStrength = 18; 
 
    halfImg = getImage().getHeight()/2; //Coordinates of Simon's feet
    simonHalfWidth = getImage().getWidth()/2;
    
    isFacingRight = true; //True if Simon is facing right
    isJumping = false; //True if Simon is jumping
    isWhipping = false;
    isOnStairs=false;
    wasOnStairs=false;
    alive=true;
    pissedOff = false;
    stairDirection=0;
    
    whipRight = new GreenfootImage[3];
    whipLeft = new GreenfootImage[3];
    walkRight = new GreenfootImage[3];
    walkLeft = new GreenfootImage[3];
    
    soundBite = new WavPlayer();
    
    walkRightCounter = 0;
    walkLeftCounter = 0;
        
        
    //Fill image arrays for animation
    fillImages();
  
    }
    
    public void run(){
        
        while(alive){
             
            
             checkKeys();
             fall();
             
             //Can't jump through blocks
             if (theWorld.isGround(getX(), getY() - halfImg))
                vSpeed = 0;
                
             if (theWorld.getLevel() == 3 && (theWorld.getScrollPos() < -1495 && theWorld.getScrollPos() > -1505) && !pissedOff)
             {
                soundBite.open("pisses.wav");
                soundBite.setLoops(1);
                soundBite.play(); 
                pissedOff = true;
             }
             
            if (getY() > (theWorld.worldHeight - 60))
                theWorld.gameOver();
             
             try{
                 t.sleep(20);
                }catch (InterruptedException e){}
            
        }
        
    }
    
    //Allows the world to be imported to Player class
    //Gives you access to the world
    public void addedToWorld(World world)
    {
        theWorld = (retroWorld)world;
        health = theWorld.getHealth();
        t=new Thread(this);
        t.start();
      
    }

    /** Check keyboard input
     * 
     */
    private void checkKeys()
    {
        //Move left (Can't go through walls or pipes)
        /*
        if (Greenfoot.isKeyDown("a") && !isWhipping && (!theWorld.isGround(getX() - simonHalfWidth, getY() + 25)))
        {
            isFacingRight = false;

            if ((theWorld.middle - getX()) > 10 && getX() < (theWorld.worldWidth - 5))
            {
                if(isOnStairs)
                    if( theWorld.getStairDirection(getX(), getY() + halfImg)==-1)
            moveUpStairs();
                
                else if(theWorld.isStairs(getX(), getY() + halfImg))
                    isOnStairs=true;
          
                moveLeft();
            }
            
            else if(theWorld.canScrollWorld(-1))
            {
                if(isOnStairs)
                    if(theWorld.getStairDirection(getX(), getY() + halfImg) == -1)
                     moveUpStairs();
                
                 
                    else if(theWorld.isStairs(getX(), getY() + halfImg))
                     isOnStairs=true;

             theWorld.scrollWorld(-1);
             }

            else if(getX()>10)
                moveLeft();
        }
        */
        
        if (Greenfoot.isKeyDown("w") && !isWhipping)
        {
        if(theWorld.isStairs(getX(), getY() + halfImg))
        isOnStairs=true;

            wasOnStairs=true;
        }
        
        //move right (Can't go through walls or pipes)
        if (/*Greenfoot.isKeyDown("d") && */!isWhipping && (!theWorld.isGround(getX() + simonHalfWidth, getY() + 25)))
        {
            isFacingRight = true;

            if ((theWorld.middle - getX()) > 10 && getX() < (theWorld.worldWidth - 5))
            {
                if(isOnStairs)
                    if(theWorld.getStairDirection(getX(), getY() + halfImg) == 1)
                      moveUpStairs();

                    else if(theWorld.isStairs(getX(), getY() + halfImg))
                      isOnStairs=true;

                moveRight();
                
            }

            else if(theWorld.canScrollWorld(1))
            {
            
                if(isOnStairs)
                {
                  if(theWorld.getStairDirection(getX(), getY() + halfImg)==1)
                     moveUpStairs();
                }
                else if(theWorld.isStairs(getX(), getY() + halfImg))
                  isOnStairs=true;

                theWorld.scrollWorld(1);
            }
            else if(getX()<595)
                moveRight();      
        }

        //jump
        if (Greenfoot.isKeyDown("z") )
        {
            if (theWorld.isGround(getX(), getY() + halfImg) || theWorld.isStairs(getX(), getY() + halfImg))
            {
                isJumping = true;
                jump();
            }
        }

        //whip
        if (Greenfoot.isKeyDown("k"))
        {
            if(isWhipping == false)
            {
                //isWhipping = true;
                setWhip();
                whip();
            }
        }
    }

    /** Make Simon jump
     * 
     */
    private void jump()
    {
        if (isFacingRight)
            setImage("SimonJumpRight.png");
        //else
            //setImage("SimonJumpLeft.png");           
            
        vSpeed = -jumpStrength;
        fall();
    }
    
    /** Move Simon to the left
     * 
     */
    public void moveLeft()
    {
        cycleLeft();
        setLocation ((getX() - speed), getY());
    }
    
    /** Move Simon to the right
     * 
     */
    public void moveRight()
    {
        cycleRight(getX());
        setLocation ((getX() + speed), getY());
    }
     
    /** Fall toward the ground
     * 
     */
    private void fall()
    {
        vSpeed = vSpeed + acceleration;
        
        //detect collision with ground pixel by pixel
        for (int i = 0; i <= vSpeed; i++)
        {
            if (theWorld.isGround(getX(), getY() + halfImg + i))
            {
                vSpeed = 0;
                isJumping = false;
                setLocation(getX(), getY() + i);
                isOnStairs=false;
                wasOnStairs=false;
            }

        if(theWorld.isStairs(getX(), getY() + halfImg + i))
        {
            vSpeed = 0;
            isJumping = false;
            if(wasOnStairs)
            isOnStairs=true;
            setLocation(getX(), getY() + i);
                }
        }
        
        setLocation (getX(), (getY() + vSpeed));
    }
    
    /** Attack by Whipping
     * 
     */
    private void whip()
    {
     
       try{
           
           
        if (isFacingRight)
        {
            setImage(whipRight[0]);
            setLocation (getX() + 10, getY());
            t.sleep(100);
            fall();
            fall();
            fall();
            setImage(whipRight[1]);
            setLocation (getX(), getY());
            t.sleep(100);
            fall();
            fall();
            fall();
            setImage(whipRight[2]);
            setLocation (getX(), getY());
            t.sleep(100);
            fall();
            fall();
            fall();
            setImage(walkRight[0]);
            setLocation(getX() - 10, getY());          
        }        
        
        else
        {
            setImage(whipLeft[0]);
            setLocation (getX() - 10, getY());
            t.sleep(100);
            fall();
            fall();
            fall();
            setImage(whipLeft[1]);
            setLocation (getX(), getY());
            t.sleep(100);
            fall();
            fall();
            fall();
            setImage(whipLeft[2]);
            setLocation (getX(), getY());
            t.sleep(100);
            fall();
            fall();
            fall();
            setImage(walkLeft[0]);
            setLocation(getX() + 10, getY());
        }
        
        t.sleep(50);
        
        
    }catch (InterruptedException e){}
        //isWhipping = false;
        setWhip();
        
       
    }
    
    /** Fill Simon's sprites
     * 
     */
    private void fillImages()
    {
        for (int i = 0; i < 3; i++)
        {
            whipRight[i] = new GreenfootImage("SimonWhipRight" + (i + 1) + ".png");
            //whipLeft[i] = new GreenfootImage("SimonWhipLeft" + (i + 1) + ".png");
            walkRight[i] = new GreenfootImage("SimonWalkRight" + (i + 1) + ".png");
            //walkLeft[i] = new GreenfootImage("SimonWalkLeft" + (i + 1) + ".png");
        }
    }
    
    /** Cycle Simon's sprites as he moves to the right
     * 
     */
    public void cycleRight(int x)
    {
        //Set each image once every 10 pixels for smoother movement
        if ((x % 10 == 0) && !isJumping)
        {
            setImage(walkRight[walkRightCounter % 3]);
            walkRightCounter++;
        }
    }
    
    /** Cycle Simon's Sprites as he moves left
     * 
     */
    public void cycleLeft()
    {
        //Set each image once every 10 pixels for smoother movement
        if ((getX() % 10 == 0) && !isJumping)
        {
            setImage(walkLeft[walkLeftCounter % 3]);
            walkLeftCounter++;        
        }
    }
    
    /** True if Simon is in a whipping animation
     * 
     */
    public boolean isCurrentlyWhipping()
    {
        return isWhipping;
    }

    /** True if Simon is alive
     * 
     */
    public boolean isAlive(){ return alive;} 
    
    /** Move Simon up stairs
     * 
     */
    public void moveUpStairs()
    {
        setLocation(getX(), (getY() - 4));
    }
    
    private  void setWhip()
    {
        isWhipping = !isWhipping;
    }
    
    /** True if Simon is facing right
     * 
     */
    public boolean facingRight()
    {
        return isFacingRight;
    }
    
    /** Called when Simon is killed
     * 
     */
    public void dead(){
        //t=null;
        //theWorld.removeObject(this);
        alive=false;
    }
    
}
